home *** CD-ROM | disk | FTP | other *** search
/ Mac Action 1996 January / mac-action-07.iso / mac / Shareware / Education / Kid's Clicks! 1.0.2 / Kid's Clicks! Source Code ƒ / Kid's Clicks!(1.0.2).π.c < prev   
Encoding:
C/C++ Source or Header  |  1995-10-06  |  28.9 KB  |  1,254 lines  |  [TEXT/KAHL]

  1. /*******************************************************/ 
  2. /*                  "Kid's Clicks"                       */
  3. /*                        (v1.0.1)                       */
  4. /*           Original version created: July 1995            */
  5. /*                                                       */
  6. /*                       For Allie                         */
  7. /*                                                       */
  8. /*       Created By Eric Long - AOL: EricMLong         */
  9. /*                                CIS: 72764,1072           */
  10. /*******************************************************/
  11.  
  12. /*    This program is pretty much a plain old modeless dialog. It will display a
  13.     picture and allow users to click on places in the picture, defined by user
  14.     items, to hear corresponding sounds played.  The picture will be scaled to
  15.     full screen size, up to 640 x 480.  If the resolution of the screen is
  16.     greater, the window will be sized to 640 x 480 and centered, revealing a
  17.     title bar and close box.
  18.  
  19.     Kid's Clicks requires system seven; it wouldn't be hard to make it 6 compatible,
  20.          but I'm not real keen on doing it.  How long should 6 be kept on the respirator?
  21.     I set up a requirement for 256 colors, which also isn't really necessary, but I
  22.         felt it was reasonable and helps eliminate a lot of hassles with modules.
  23.         
  24. */
  25.     
  26. /*    Version History:
  27.  
  28.     1.0.1     Corrections - 
  29.                 CheckSystemEnvironment Routine Now Works with 16bit monitors.
  30.         
  31.     1.0.2     Corrections -
  32.                 AboutModuleFilter() error corrected setting port with temp variable
  33.     
  34.             Changes -
  35.                 New routine added: GetNew_Module_CDialog.
  36.                 Modified Install_KidsModule() and Adjust_Module_ToFitScreen()
  37.                     to fit with new routine.
  38.                 
  39.                     Now users running in 256 colors will see dramatic image quality
  40.                     improvement with PICTs that do not use standard system colors. 
  41.                     This routine was derived from example source code on the DEVELOP
  42.                     CD, by Nick Thompson of Apple.
  43.                 
  44.                 Added watch cursor while loading modules. See Open_KidsModule().
  45.  
  46.                 KC memory allocation increased to 1050K from 700K.
  47.                     This overcomes a not-so-bright idea I introduced into modules,
  48.                     by using the module's PICT in the module About screen.
  49.                     Why is that not so bright?  Because it causes KC to need a lot
  50.                     more memory, or it begins to corrupt itself after users select
  51.                     "About the module…".  Mea Culpa.
  52.         
  53. */
  54.  
  55.  
  56. #include    <AppleEvents.h>
  57. #include    <Sound.h>
  58. #include    <PictUtil.h>
  59. #include    <Palettes.h>
  60. #include    <QDOffscreen.h>
  61. #include    <GestaltEqu.h>
  62. #include    <string.h>
  63. #include    <stdio.h>
  64.  
  65. /*     konstants     */
  66.  
  67. #define     kKidsClicksSig            'Kydz'
  68. #define     kThisVersion            1
  69.  
  70. #define     kBaseResID                128
  71. #define     rErrorAlertID            501
  72. #define     rWrongVersionAlert        502
  73. #define     rErrStringsID            128
  74. #define         eCantOpenMultiModules    1
  75. #define         eNotAKidsModule            2
  76. #define         eUnableToOpenFile        3
  77. #define         eWrongSysEnvirons        4
  78. #define         eNotEnoughMemory        5
  79.  
  80. #define     kAboutScreenFilter    (ProcPtr)&AboutScreenFilter
  81. #define     rAboutSnd        500
  82. #define     kAboutDlgMem    sizeof(DialogRecord)
  83. #define     rAboutDlgID    500
  84. #define         iAllieFrame    2
  85. #define     rAlliePictID            1000
  86.  
  87. #define     kKidsModuleType        'Kmod'
  88. #define     kModuleBaseResID        5000
  89. #define     rAboutModuleID            1000
  90. #define     rExpectedPICTID        5000
  91. #define     rExpectedSndID            9001
  92.  
  93. #define     kSleep            20L
  94. #define     sEmptyString    "\p"
  95. #define     kSystemSeven    0x00000700L
  96. #define     k256ColorDepth    8
  97.  
  98. /* Window Stuff */
  99. #define    kMoveToFront        (WindowPtr)-1L
  100.  
  101. /* Menus */
  102. #define        mApple            kBaseResID
  103. #define            iAbout            1
  104. #define             iAboutModule    2
  105.  
  106. #define        mFile            kBaseResID+1
  107. #define             iOpen        1
  108. #define             iClose        2
  109. #define             iQuit        4
  110.  
  111. #define         mScramble        kBaseResID+2
  112. #define             iScramble    1
  113. #define             iUnscramble    2
  114.  
  115. #define         mDirections        kBaseResID+3
  116. #define         rDirectionStrings    129
  117. #define         sOpenModule            1
  118. #define         sClickMouse            2
  119.  
  120.  
  121. /* Module port Size Info */
  122. #define     kMaxModuleWidth    640
  123. #define     kMaxModuleHeight    480
  124.  
  125. const RGBColor    kRGBBlack = {0, 0, 0};
  126. const RGBColor    kRGBWhite = {0xFFFF, 0xFFFF, 0xFFFF};
  127.  
  128.  
  129. typedef struct DLOGRsrcRec
  130. {
  131.     Rect    boundsRect;
  132.     short   procID;
  133.     char    visible;
  134.     char    filler;
  135.     char    goAwayFlag;
  136.     char    filler2;
  137.     long    refCon;
  138.     Str255  title;
  139. }DLOGRsrcRec, *DLOGRsrcPtr, **DLOGRsrcHandle;
  140.  
  141.  
  142. /************************* Globals ******************************/
  143.  
  144. Boolean            gModuleIsLoaded, gDone, gFatal, gSoundsAreScrambled;
  145. DialogPtr        gModuleDialog;
  146. short            gKidsModuleResNum, gSoundOrder[255];
  147. PaletteHandle    gPICTPalette;
  148. CTabHandle        gPICTCTab;
  149.  
  150.  
  151. /************************ Prototypes **********************************/
  152.  
  153. void            main( void );
  154. void            ToolBoxInit ( void );
  155. void            AEInit( void );
  156. void            MenuBarInit( void );
  157. void            EventLoop ( void );
  158. void            DoEvent( EventRecord *eventPtr );                            
  159. Boolean            DoUpdate( WindowPtr window );
  160. void            HandleNull( EventRecord *event );
  161. void            HandleKeyDown(EventRecord *eventPtr);
  162. void            HandleMouseDown (EventRecord *eventPtr );
  163. void            HandleMenuChoice( long menuChoice );
  164. void            HandleAppleChoice( short item );
  165. void            HandleFileChoice( short item );
  166. void            HandleScrambleChoice( short item );
  167. void            Get_KidsModule( void );
  168. void            Open_KidsModule( FSSpec *kidsModule );
  169. Boolean            Verify_KidsModule(short myResNum);
  170. Boolean            Verify_Resource( OSType rType, short rID );
  171. void            Check_KCModuleVersion( void );
  172. OSErr            Install_KidsModule( short myResNum );
  173. OSErr            GetNew_Module_CDialog( void ); 
  174. void            Adjust_Module_ToFitScreen( DialogPtr dialog );
  175. void            Close_KidsModule( void );
  176. void            Handle_KidsClicks( EventRecord *eventPtr );
  177. void            PlaySound( short whichSound );
  178. void            ScrambleSoundOrder( void );
  179. void            Do_AboutDialog( void );
  180. void            Do_AboutModuleDlg( void );
  181. pascal Boolean    AboutScreenFilter( DialogPtr dialog, EventRecord *event,
  182.                                     short *itemHit );
  183. pascal void        rectProc( DialogPtr theDialog, short item );
  184.  
  185.     /* Apple Events Required Suite */
  186. pascal OSErr    DoOpenApp( AppleEvent theAppleEvent,
  187.                            AppleEvent reply, long refCon );
  188. pascal OSErr    DoOpenDoc( const AppleEvent *theAppleEvent,
  189.                             AppleEvent *reply, long refCon );
  190. pascal OSErr    DoPrintDoc( AppleEvent theAppleEvent,
  191.                             AppleEvent reply, long refCon );
  192. pascal OSErr    DoQuitApp( AppleEvent theAppleEvent,
  193.                             AppleEvent reply, long refCon );
  194.  
  195. void            DoError( short err );
  196. Boolean            CheckSystemEnvironment( void );
  197. void            Pstrcpy( Str255 *destString, Str255 srcString);
  198.  
  199.  
  200. /******************** main ***********************************/
  201.  
  202. void        main ( void )
  203. {
  204.         ToolBoxInit ();
  205.         MaxApplZone();
  206.         if (!CheckSystemEnvironment())
  207.         {
  208.             gFatal = true;
  209.             DoError(eWrongSysEnvirons);
  210.         }
  211.         else
  212.         {
  213.             MenuBarInit();
  214.             AEInit();
  215.             
  216.             FlushEvents( everyEvent, 0 );        
  217.             EventLoop();
  218.         }
  219. }
  220.         
  221.  
  222. /************************* ToolBoxInit ******************************/
  223.  
  224. void        ToolBoxInit ( void )
  225. {
  226.     InitGraf ( &thePort );
  227.     InitFonts ();
  228.     InitWindows ();
  229.     InitMenus ();
  230.     TEInit ();
  231.     InitDialogs ( nil );
  232.     InitCursor ();
  233. }
  234.  
  235.  
  236. /*********************** AEInit ***************************/
  237.  
  238. void    AEInit( void )
  239. {
  240.     OSErr    ignoreErr;
  241.     
  242.     ignoreErr = AEInstallEventHandler ( kCoreEventClass,
  243.         kAEOpenApplication, DoOpenApp, 0L, false );
  244.     
  245.     ignoreErr = AEInstallEventHandler ( kCoreEventClass,
  246.         kAEOpenDocuments, DoOpenDoc, 0L, false );
  247.     
  248.     ignoreErr = AEInstallEventHandler ( kCoreEventClass,
  249.         kAEPrintDocuments, DoPrintDoc, 0L, false );
  250.  
  251.     ignoreErr = AEInstallEventHandler ( kCoreEventClass,
  252.         kAEQuitApplication, DoQuitApp, 0L, false );
  253. }
  254.  
  255.  
  256. /*********************** MenuBarInit ***************************/
  257.  
  258. void    MenuBarInit( void )
  259. {
  260.     Handle            menuBar;
  261.     MenuHandle        menu;
  262.     Str255            directionStr;
  263.     
  264.     menuBar = GetNewMBar( kBaseResID );
  265.     SetMenuBar( menuBar );
  266.     
  267.     menu = GetMHandle( mApple );
  268.     AddResMenu( menu, 'DRVR' );
  269.     
  270.     DrawMenuBar();
  271.     
  272.     menu = GetMHandle(mDirections);
  273.     GetIndString( directionStr, rDirectionStrings, sOpenModule );
  274.     SetItem(menu, 1, directionStr);    
  275. }
  276.  
  277.  
  278. /************************ EventLoop ************************/
  279.  
  280. void    EventLoop ( void )
  281. {
  282.     EventRecord        event;
  283.     
  284.     gModuleIsLoaded = gDone = gFatal = gSoundsAreScrambled = false;
  285.  
  286.     while ( !gDone )
  287.     {
  288.         if ( WaitNextEvent( everyEvent, &event, kSleep, nil) )
  289.                 DoEvent ( &event );
  290.         else
  291.             HandleNull( &event );
  292.     }
  293. }
  294.  
  295.  
  296. /************************** DoEvent ***********************/
  297.  
  298. void    DoEvent( EventRecord *eventPtr )
  299. {    
  300.     switch ( eventPtr->what )
  301.     {
  302.         case kHighLevelEvent:
  303.             AEProcessAppleEvent( eventPtr );
  304.             break;
  305.         case keyDown:
  306.         case autoKey:
  307.             HandleKeyDown(eventPtr);
  308.             break;
  309.         case mouseDown:
  310.             HandleMouseDown( eventPtr );
  311.             break;
  312.         case updateEvt:
  313.             DoUpdate((WindowPtr)eventPtr->message);
  314.             break;
  315.     }             
  316. }
  317.  
  318.  
  319. /********************* DoUpdate ******************************/
  320.  
  321. Boolean        DoUpdate( WindowPtr    window )
  322. {
  323.     Boolean        isMyWindow = false;
  324.     
  325.     isMyWindow = (window == (WindowPtr)gModuleDialog);
  326.     if (isMyWindow)
  327.     {
  328.         BeginUpdate( window );
  329.         UpdtDialog((DialogPtr)window, window->visRgn);
  330.         EndUpdate( window );
  331.     }
  332.     
  333.     return (isMyWindow);
  334. }
  335.  
  336.  
  337. /******************* HandleNull **************************/
  338.  
  339. void    HandleNull( EventRecord *eventPtr )
  340. {
  341.     ;
  342. }        
  343.  
  344.  
  345. /******************** HandleKeyDown ****************************/
  346.  
  347. void    HandleKeyDown(EventRecord *eventPtr)
  348. {
  349.     char            theChar;
  350.         
  351.     theChar = eventPtr->message & charCodeMask;
  352.     if ( (eventPtr->modifiers & cmdKey) != 0 )
  353.         HandleMenuChoice( MenuKey( theChar ) );
  354. }
  355.  
  356.  
  357. /******************* HandleMouseDown **************************/
  358.  
  359. void    HandleMouseDown ( EventRecord *eventPtr )
  360. {
  361.     WindowPtr        window;
  362.     short            thePart;
  363.     long            menuChoice;
  364.     
  365.     thePart = FindWindow ( eventPtr->where, &window );
  366.     
  367.     switch ( thePart )
  368.     {
  369.         case inMenuBar:
  370.             menuChoice = MenuSelect( eventPtr->where );
  371.             HandleMenuChoice( menuChoice );
  372.             break;
  373.         case inSysWindow :
  374.             SystemClick ( eventPtr, window );
  375.             break;
  376.         case inDrag :
  377.             DragWindow ( window, eventPtr->where,
  378.                         &screenBits.bounds );
  379.             break;
  380.         case inContent:
  381.             Handle_KidsClicks(eventPtr);
  382.             break;
  383.         case inGoAway:
  384.             Close_KidsModule();
  385.             break;
  386.     }
  387. }
  388.  
  389.  
  390. /********************** HandleMenuChoice **************************/
  391.  
  392. void    HandleMenuChoice( long menuChoice )
  393. {
  394.     short        menu;
  395.     short        item;
  396.     
  397.     if ( menuChoice != 0 )
  398.     {
  399.         menu = HiWord( menuChoice );
  400.         item = LoWord( menuChoice );
  401.         
  402.         switch( menu )
  403.         {
  404.             case mApple:
  405.                 HandleAppleChoice( item );
  406.                 break;
  407.             case mFile:
  408.                 HandleFileChoice( item );
  409.                 break;
  410.             case mScramble:
  411.                 HandleScrambleChoice( item );
  412.                 break;
  413.         }
  414.         HiliteMenu( 0 );
  415.     }
  416. }
  417.  
  418.  
  419. /********************* HandleAppleChoice ***************************/
  420.  
  421. void    HandleAppleChoice( short item )
  422. {
  423.     MenuHandle    appleMenu;
  424.     Str255        accName;
  425.     short        accNumber;
  426.     
  427.     switch ( item )
  428.     {
  429.         case iAbout:
  430.             Do_AboutDialog();
  431.             break;
  432.         case iAboutModule:
  433.             Do_AboutModuleDlg();
  434.             break;
  435.         default:
  436.             appleMenu = GetMHandle( mApple );
  437.             GetItem( appleMenu, item, accName );
  438.             accNumber = OpenDeskAcc( accName );
  439.             break;
  440.     }
  441. }
  442.  
  443.  
  444. /********************* HandleFileChoice ****************************/
  445.  
  446. void    HandleFileChoice( short item )
  447. {        
  448.     switch(item)
  449.     {
  450.         case iOpen:
  451.             Get_KidsModule();
  452.             break;
  453.         case iClose:
  454.             Close_KidsModule();
  455.             break;
  456.         case iQuit:
  457.             if (gModuleIsLoaded)
  458.                 Close_KidsModule();
  459.             gDone = true;
  460.             break;
  461.     }
  462. }
  463.  
  464.  
  465. /******************** HandleScrambleChoice ***************************/ 
  466.  
  467. void    HandleScrambleChoice( short item )
  468. {
  469.     MenuHandle    menu;
  470.     
  471.     switch(item)
  472.     {
  473.         case iScramble:
  474.             ScrambleSoundOrder();
  475.             break;
  476.         case iUnscramble:
  477.             gSoundsAreScrambled = false;
  478.             menu = GetMHandle(mScramble);
  479.             DisableItem(menu, iUnscramble);
  480.             break;
  481.     }
  482. }
  483.  
  484.  
  485. /*********************** Get_KidsModule ******************************/ 
  486.  
  487. void    Get_KidsModule( void )
  488. {
  489.     FSSpec        kidsModule;
  490.     SFReply        reply;
  491.     SFTypeList    fileList;
  492.     Point        where;
  493.     
  494.     fileList[0] = kKidsModuleType;
  495.     where.h = where.v = 100;
  496.     SFGetFile( where, nil, nil, 1, fileList, nil, &reply);
  497.     if (reply.good)
  498.     {
  499.         FSMakeFSSpec( reply.vRefNum, 0, reply.fName, &kidsModule );
  500.         Open_KidsModule( &kidsModule );
  501.     }
  502. }
  503.  
  504.  
  505. /************************ Open_KidsModule ***************************/ 
  506.  
  507. void        Open_KidsModule( FSSpec *kidsModule )
  508. {
  509.     short    myResNum, err;
  510.     FInfo    moduleInfo;
  511.     CursHandle        waitCursH;
  512.     Cursor            waitCursor;
  513.     
  514.     waitCursH = GetCursor(watchCursor);
  515.     HLock((Handle)waitCursH);
  516.     waitCursor = **waitCursH;
  517.     HUnlock(waitCursH);
  518.     ReleaseResource(waitCursH);
  519.     
  520.     SetCursor(&waitCursor);    // put up the watch cursor
  521.     
  522.     err = HGetFInfo( kidsModule->vRefNum, kidsModule->parID,
  523.                                         kidsModule->name, &moduleInfo );
  524.     if (err)
  525.     { 
  526.         DoError(eUnableToOpenFile);
  527.         goto cantDoIt;
  528.     }    // System Error
  529.     
  530.         /* Make sure it's our document type */
  531.     if ((moduleInfo.fdType != kKidsModuleType)
  532.                 || (moduleInfo.fdCreator != kKidsClicksSig))
  533.     {
  534.         DoError(eNotAKidsModule);
  535.         goto    cantDoIt;
  536.     }    
  537.     
  538.         /* Open it */
  539.     myResNum = HOpenResFile(kidsModule->vRefNum, kidsModule->parID,
  540.                                             kidsModule->name, fsCurPerm);
  541.     
  542.     if (Verify_KidsModule(myResNum))
  543.     {
  544.         if (gModuleIsLoaded)
  545.             Close_KidsModule();
  546.         err = Install_KidsModule(myResNum);
  547.         if (err)
  548.         {
  549.             DoError(err);
  550.             goto cantDoIt;
  551.             gModuleIsLoaded = false;
  552.         }
  553.         gKidsModuleResNum = myResNum;
  554.         gModuleIsLoaded = true;
  555.         Check_KCModuleVersion();
  556.     }
  557.     else
  558.     {
  559.         CloseResFile(myResNum);
  560.         DoError(eNotAKidsModule);
  561.     }
  562.  
  563. cantDoIt:
  564.     SetCursor(&arrow);
  565. }
  566.  
  567.  
  568. /*********************** Verify_KidsModule ****************************/ 
  569.  
  570. Boolean        Verify_KidsModule(short myResNum)
  571. {
  572.     Boolean        itIs = false;
  573.     Handle        myResource;
  574.     
  575.     // Check out the data in the module file, see if it appears to actually
  576.     // be a Kid's Clicks module
  577.     
  578.     itIs = Verify_Resource('PICT', rExpectedPICTID);    // Screen PICT
  579.     itIs = Verify_Resource('DLOG', kModuleBaseResID);            // The Dialog
  580.     itIs = Verify_Resource('snd ', rExpectedSndID);        // Make sure there's sounds
  581.     itIs = Verify_Resource('STR ', kModuleBaseResID);        // About… string for module
  582.     itIs = Verify_Resource('ALRT', rAboutModuleID); // About… Dialog
  583.     itIs = Verify_Resource('vers', kBaseResID);    // Module Designed For Version#
  584.     
  585.     // If itIs still is after those tests, I'm convinced. 
  586.     return(itIs);
  587. }
  588.  
  589.  
  590. /************************ Verify_Resource ******************************/ 
  591.  
  592. Boolean        Verify_Resource( OSType rType, short rID )
  593. {
  594.     Boolean        resOK = false;
  595.     Handle        rHandle;
  596.     
  597.     // Verify existance of resource
  598.     rHandle = GetResource( rType, rID );
  599.     if (rHandle)
  600.         resOK = true;
  601.     ReleaseResource(rHandle);
  602.     
  603.     return(resOK);
  604. }
  605.  
  606.  
  607. /************************ Check_KCModuleVersion ******************************/ 
  608.  
  609. void    Check_KCModuleVersion( void )
  610. {
  611.     Handle    versHandle;
  612.     short    version = 1;
  613.     Str255    versString;
  614.     
  615.         // This routine looks to see if the module is meant for a newer version
  616.         // of the app than this version.  If so, an alert tells the user and
  617.         // notifies them that some features of the module might not work
  618.         // if the present version of Kid's Clicks doesn't handle those features. 
  619.     
  620.     versHandle = GetResource('vers', kBaseResID);
  621.     if (versHandle)
  622.         version = **versHandle;
  623.     ReleaseResource(versHandle);
  624.     
  625.     if (version > kThisVersion)
  626.     {
  627.         PtoCstr(versString);
  628.         sprintf(versString, "%d.0", version);
  629.         CtoPstr(versString);
  630.         ParamText(versString, sEmptyString, sEmptyString, sEmptyString);
  631.         NoteAlert(rWrongVersionAlert, nil);
  632.     }
  633.     
  634. }
  635.  
  636.  
  637. /********************* Install_KidsModule **************************/ 
  638.  
  639. OSErr        Install_KidsModule( short myResNum )
  640. {
  641.     StringHandle    strHandle;
  642.     Handle            menu;
  643.     Str255            aboutString;
  644.     OSErr            myErr = 0;
  645.     Str255            directionStr;
  646.     GWorldPtr        theNewWorld;
  647.         
  648.     myErr = GetNew_Module_CDialog();
  649.     if (! gModuleDialog)
  650.         goto moduleIncomplete;
  651.     
  652.     SetPort(gModuleDialog);
  653.     Adjust_Module_ToFitScreen(gModuleDialog);
  654.     ShowWindow(gModuleDialog);
  655.     
  656.         // All this for the module "About" String
  657.     strHandle = GetString(kModuleBaseResID);
  658.     HLock(strHandle);
  659.     Pstrcpy(aboutString, *strHandle);
  660.     HUnlock(strHandle);
  661.     ReleaseResource(strHandle);
  662.     
  663.     menu = GetMHandle(mApple);
  664.     InsMenuItem(menu, aboutString, 1);
  665.     
  666.     menu = GetMHandle(mFile);
  667.     EnableItem(menu, iClose);
  668.     
  669.     menu = GetMHandle(mScramble);
  670.     EnableItem(menu , 0);
  671.     EnableItem(menu, iScramble);
  672.     DrawMenuBar();
  673.     
  674.     menu = GetMHandle(mDirections);
  675.     GetIndString(directionStr, rDirectionStrings, sClickMouse);
  676.     SetItem(menu, 1, directionStr);
  677.     
  678. moduleIncomplete:    
  679.     return(myErr);
  680. }
  681.  
  682.  
  683. /************************ GetNew_Module_CDialog **************************/ 
  684.  
  685. OSErr    GetNew_Module_CDialog( void ) 
  686. {
  687.     OSErr            theErr = 0;
  688.     Handle            module_itemList;        
  689.     DLOGRsrcHandle    module_DLOG;
  690.     Rect            theRect;
  691.     CGrafPtr        savedPort;
  692.     GWorldPtr        savedGWorld;
  693.     GWorldPtr        theNewWorld;
  694.     GDHandle        oldDevice;
  695.     PicHandle        modulePicture;
  696.     PictInfo        thePictInfo;
  697.     
  698.     
  699.     /* To make the picture look pretty, we'll set the color environment to suit    */
  700.                             
  701.     modulePicture = GetPicture(kModuleBaseResID);    // Get the module's picture
  702.     if (!modulePicture)
  703.     {
  704.         theErr = eUnableToOpenFile;
  705.         goto end_GetNew_Module_CDialog;
  706.     }
  707.     
  708.     /*    Create an offscreen gWorld with the color environment needed  */
  709.     
  710.         // Use Rect from the module's DLOG resource
  711.     module_DLOG = GetResource('DLOG', kModuleBaseResID);
  712.     theRect = (**module_DLOG).boundsRect;
  713.     ReleaseResource(module_DLOG);
  714.         
  715.         // Set up a palette and color table from module picture
  716.     theErr = GetPictInfo( modulePicture, &thePictInfo, returnColorTable, 256, systemMethod, 0);
  717.     ReleaseResource(modulePicture);    // Let it go, we don't need it anymore 
  718.  
  719.     gPICTPalette = NewPalette( 256, thePictInfo.theColorTable, pmTolerant, 0x1000 );
  720.     gPICTCTab = thePictInfo.theColorTable;
  721.     
  722.         // Create the offscreen gWorld, 8 bits deep (256 Colors)
  723.     theErr = NewGWorld( &theNewWorld, 8, &theRect, gPICTCTab, nil, 0L );
  724.     if( theErr != noErr )
  725.     {
  726.         theErr = eNotEnoughMemory;
  727.         goto end_GetNew_Module_CDialog;
  728.     }
  729.             
  730.         // Save the current gWorld
  731.     GetGWorld( &savedPort, &oldDevice );
  732.     
  733.         // Initialize some parameters of the offscreen gWorld
  734.     SetGWorld( theNewWorld, nil );
  735.     RGBForeColor( &kRGBBlack );        // Ensure the fg and bg colors are 
  736.     RGBBackColor( &kRGBWhite );        // as anticipated.
  737.     PenMode( srcCopy );                // Ensure the transfer mode is as expected.
  738.  
  739.         // Restore the saved gWorld
  740.     SetGWorld(savedPort, oldDevice);
  741.     
  742.     
  743.     /* Using our offscreen gWorld, we will create a new color dialog for the module */
  744.     
  745.         // Load the module itemlist
  746.     module_itemList = GetResource('DITL', kModuleBaseResID);
  747.     if (! module_itemList)
  748.     {
  749.         theErr = eUnableToOpenFile;
  750.         goto end_GetNew_Module_CDialog;
  751.     }
  752.     
  753.         // Create new color dialog, store ptr to gWorld in refcon for later disposal
  754.     gModuleDialog = NewCDialog( nil, &theRect, "\pKid's Clicks!",
  755.                         false, noGrowDocProc, kMoveToFront,
  756.                                 true, (long)theNewWorld, module_itemList);
  757.     if (! gModuleDialog)
  758.     {
  759.         theErr = eUnableToOpenFile;
  760.         goto end_GetNew_Module_CDialog;
  761.     }
  762.         
  763.         // Set the module window palette            
  764.     if(gPICTPalette != nil)
  765.         SetPalette(gModuleDialog, gPICTPalette, true);
  766.     
  767.     ActivatePalette(gModuleDialog);
  768.     SetGWorld((CGrafPtr)gModuleDialog, nil);
  769.     
  770.     SetGWorld(savedPort, oldDevice);
  771.     
  772. end_GetNew_Module_CDialog:
  773.     return (theErr);
  774. }
  775.  
  776.  
  777. /*********************** Adjust_Module_ToFitScreen ****************************/ 
  778.  
  779. void            Adjust_Module_ToFitScreen( DialogPtr dialog )
  780. {
  781.     GDHandle        myDevice;
  782.     short            iType, iNum, numItems, mBarHeight;
  783.     Handle            iHandle;
  784.     Rect            iRect, oldPortRect, newPortRect;
  785.     Boolean            adjustPosition = true;
  786.     
  787.     myDevice = GetMainDevice();
  788.     newPortRect = (**myDevice).gdRect;
  789.     if ((newPortRect.right > kMaxModuleWidth)
  790.                 || (newPortRect.bottom > kMaxModuleHeight))
  791.     {
  792.         SetRect( &newPortRect, 0, 0, kMaxModuleWidth, kMaxModuleHeight);    
  793.         adjustPosition = false;    // Let it be auto-centered
  794.     }
  795.         
  796.         // Small adjustment so we don't lose part of the picture
  797.     if (adjustPosition)
  798.     {
  799.         mBarHeight = GetMBarHeight();
  800.         newPortRect.bottom -= mBarHeight;
  801.     } 
  802.     
  803.         // Save the old port Rect size
  804.     oldPortRect = (dialog->portRect);
  805.     
  806.         // Re-size the port Rect
  807.     (dialog->portRect) = newPortRect;    
  808.     
  809.     iNum = CountDITL(dialog);
  810.     if (iNum)
  811.     {
  812.             // Adjust picture's rect
  813.         GetDItem(dialog, iNum, &iType, &iHandle, &iRect);
  814.         SetDItem(dialog, iNum, iType, iHandle, &newPortRect);
  815.     
  816.             // Calculate size increase & Adjust all user items to new screen size
  817.         numItems = iNum;
  818.     
  819.         for (iNum = 1; iNum <= numItems-1; iNum++)
  820.         {
  821.                 // ReSize & Calculate Movement of User Item Rects
  822.             GetDItem(dialog, iNum, &iType, &iHandle, &iRect);
  823.             MapRect(&iRect, &oldPortRect, &newPortRect);
  824.             SetDItem(dialog, iNum, iType, iHandle, &iRect);
  825.         }
  826.     }
  827.     PortChanged((GrafPtr)dialog);
  828.     
  829.     if (adjustPosition)
  830.         MoveWindow((WindowPtr)dialog, 0, mBarHeight, false);
  831. }    
  832.  
  833.  
  834. /*********************** Close_KidsModule ****************************/ 
  835.  
  836. void    Close_KidsModule( void )
  837. {
  838.     Handle        menu;
  839.     Str255        directionStr;
  840.     GWorldPtr    module_gWorld;
  841.     
  842.     module_gWorld = (GWorldPtr)(GetWRefCon(gModuleDialog));
  843.     DisposeGWorld(module_gWorld);
  844.  
  845.     DisposDialog(gModuleDialog);
  846.     DisposCTable(gPICTCTab);
  847.     DisposePalette(gPICTPalette);
  848.     
  849.     CloseResFile(gKidsModuleResNum);
  850.     
  851.     menu = GetMHandle(mApple);
  852.     DelMenuItem(menu, 2);
  853.     
  854.     menu = GetMHandle(mFile);
  855.     DisableItem(menu, iClose);
  856.     
  857.     menu = GetMHandle(mScramble);
  858.     if (gSoundsAreScrambled)
  859.         DisableItem(menu, iUnscramble);
  860.     DisableItem(menu, 0);
  861.     DrawMenuBar();
  862.     gSoundsAreScrambled = false;
  863.     
  864.     menu = GetMHandle(mDirections);
  865.     GetIndString(directionStr, rDirectionStrings, sOpenModule);
  866.     SetItem(menu, 1, directionStr); 
  867.     
  868.     gModuleIsLoaded = false;
  869. }
  870.  
  871.  
  872. /************************* Handle_KidsClicks **********************************/ 
  873.  
  874. void    Handle_KidsClicks( EventRecord *eventPtr )
  875. {
  876.     short            itemHit;
  877.     
  878.     SetPort(gModuleDialog);
  879.     
  880.     if( DialogSelect( eventPtr, &gModuleDialog, &itemHit ) )
  881.                 PlaySound(itemHit);
  882. }
  883.  
  884.  
  885. /************************* PlaySound *******************************/
  886.  
  887. void    PlaySound( short whichSound )
  888. {
  889.     Handle    theSound;
  890.     short    mySound;
  891.     
  892.     if (gSoundsAreScrambled)
  893.         mySound = rExpectedSndID + gSoundOrder[whichSound] -1;
  894.     else    
  895.         mySound = rExpectedSndID + whichSound - 1;
  896.             
  897.     theSound = GetResource( 'snd ', mySound );
  898.     
  899.     if (theSound)
  900.     {
  901.         SndPlay( NULL, theSound, 0 );
  902.         FlushEvents( mDownMask, 0 );
  903.     }
  904.         
  905.     ReleaseResource(theSound);
  906. }
  907.     
  908.  
  909. /*********************** ScrambleSoundOrder *****************************/ 
  910.  
  911. void    ScrambleSoundOrder( void )
  912. {
  913.     short            numSounds, sndCount, saveResFile;
  914.     unsigned short    randomNum;
  915.     short            newSoundOrder[255];
  916.     long            result, range;
  917.     MenuHandle        menu;
  918.     
  919.     saveResFile = CurResFile();
  920.     
  921.     UseResFile(gKidsModuleResNum);
  922.     numSounds = Count1Resources('snd ');
  923.     
  924.     GetDateTime(&randSeed);
  925.     
  926.         // Initialize array of numbers 1 - numSounds in consecutive order
  927.     for (sndCount = 1; sndCount <= numSounds; sndCount++)
  928.     {
  929.         newSoundOrder[sndCount] = sndCount;
  930.     }
  931.     
  932.         // Create a new order by picking a number from the array at random
  933.         // Then shrinking the pot by 1 until only one is left.
  934.     for (sndCount = numSounds; sndCount > 1; sndCount--)
  935.     {
  936.         randomNum = Random();
  937.         range = sndCount;
  938.         result = (randomNum * range) / 65536 + 1;
  939.                 
  940.         gSoundOrder[sndCount] = newSoundOrder[result];
  941.         
  942.             // Remove element from array so it isn't repeated
  943.         if (result < sndCount)
  944.         {
  945.             memmove(&(newSoundOrder[result]), &(newSoundOrder[result+1]),
  946.                         (sndCount - result) * sizeof(short));
  947.         }
  948.     }
  949.     gSoundOrder[1] = newSoundOrder[1];
  950.     
  951.     if (! gSoundsAreScrambled)
  952.     {
  953.         gSoundsAreScrambled = true;
  954.         menu = GetMHandle(mScramble);
  955.         EnableItem(menu, iUnscramble);
  956.     }
  957.     UseResFile(saveResFile);
  958. }
  959.  
  960.  
  961. /************************ Do_AboutDialog ***************************/ 
  962.  
  963. void        Do_AboutDialog( void )
  964. {
  965.     DialogPtr    dialog;
  966.     Ptr            dStorage;
  967.     Boolean        done = false;
  968.     GrafPtr        savePort;
  969.     Rect        itemRect;
  970.     short        itemHit, itemType;
  971.     Handle        itemHandle, theSound;
  972.     
  973.     GetPort(&savePort);    
  974.     theSound = GetResource('snd ', rAboutSnd);
  975.  
  976.         // I allocate my own space to prevent my sound from
  977.         //    crashing memory when it is loaded.  I am still learning about
  978.         // the Mac's expectation in this area.
  979.     dStorage = NewPtrClear( kAboutDlgMem ); 
  980.     dialog = GetNewDialog( rAboutDlgID, dStorage, kMoveToFront );
  981.     if (! dialog)
  982.     {
  983.         SysBeep(10);
  984.         SysBeep(10);
  985.         DisposPtr(dStorage);
  986.         goto noDice;
  987.     }
  988.     SetPort(dialog);
  989.  
  990.     GetDItem( dialog, ok, &itemType, &itemHandle, &itemRect);
  991.     SetDialogDefaultItem( dialog, ok );
  992.     
  993.     GetDItem( dialog, iAllieFrame, &itemType, &itemHandle, &itemRect);
  994.     SetDItem(dialog, iAllieFrame, itemType, rectProc, &itemRect); 
  995.  
  996.     ShowWindow(dialog);
  997.     
  998.     while (! done){
  999.         ModalDialog(kAboutScreenFilter, &itemHit);
  1000.         if (itemHit == iAllieFrame)
  1001.             if (theSound)
  1002.                 SndPlay( NULL, theSound, 0 );
  1003.                 
  1004.         if (itemHit == ok)
  1005.             done = true;
  1006.     }
  1007.  
  1008.     CloseDialog(dialog);
  1009.     DisposPtr(dStorage);
  1010. noDice:
  1011.     ReleaseResource(theSound);
  1012.     SetPort(savePort);
  1013. }
  1014.  
  1015.  
  1016. /************************ Do_AboutModuleDlg ***************************/ 
  1017.  
  1018. void        Do_AboutModuleDlg( void )
  1019. {
  1020.     DialogPtr    dialog;
  1021.     Boolean        done = false;
  1022.     Ptr            dStorage;
  1023.     GrafPtr        savePort;
  1024.     Rect        itemRect;
  1025.     short        itemHit, itemType;
  1026.     Handle        itemHandle;
  1027.     
  1028.     GetPort(&savePort);    
  1029.     dStorage = NewPtrClear( kAboutDlgMem );
  1030.     dialog = GetNewDialog( rAboutModuleID, dStorage, kMoveToFront );
  1031.     if (! dialog)
  1032.     {
  1033.         SysBeep(10);
  1034.         SysBeep(10);
  1035.         goto noDice;
  1036.     }
  1037.     SetPort(dialog);
  1038.     GetDItem( dialog, ok, &itemType, &itemHandle, &itemRect);
  1039.     SetDialogDefaultItem( dialog, ok );
  1040.             
  1041.     ShowWindow(dialog);
  1042.     
  1043.     while (! done){
  1044.         ModalDialog(kAboutScreenFilter, &itemHit);
  1045.         if (itemHit == ok)
  1046.             done = true;
  1047.     }
  1048.     
  1049.     CloseDialog(dialog);
  1050.     DisposPtr(dStorage);
  1051. noDice:
  1052.     SetPort(savePort);
  1053. }
  1054.  
  1055.  
  1056. /****************** AboutScreenFilter ******************************/
  1057.  
  1058. pascal Boolean    AboutScreenFilter( DialogPtr dialog, EventRecord *event,
  1059.                                     short *itemHit )
  1060. {
  1061.     Boolean         returnVal = false;
  1062.     WindowPtr        temp;
  1063.     ProcPtr            *standardProc;
  1064.             
  1065.     if ( (event->what == updateEvt) && ((WindowPtr)event->message != dialog) )
  1066.     {
  1067.         returnVal = DoUpdate((WindowPtr)event->message);
  1068.     }
  1069.     else{
  1070.         GetPort(&temp);
  1071.         SetPort(dialog);
  1072.         GetStdFilterProc(&standardProc);
  1073.         returnVal = ((ModalFilterProcPtr)standardProc)
  1074.             (dialog, event, itemHit );
  1075.                         
  1076.         SetPort(temp);
  1077.     }
  1078.     return returnVal;
  1079. }    
  1080.  
  1081.  
  1082. /******************** rectProc *************************/
  1083.  
  1084. pascal void        rectProc( DialogPtr theDialog, short item )
  1085. {
  1086.     short     type;
  1087.     Rect    theRect;
  1088.     Handle    itemHandle;
  1089.     
  1090.     GetDItem( theDialog, item, &type, &itemHandle, &theRect);
  1091.     PenSize(3,3);
  1092.     FrameRect( &theRect );
  1093.     PenNormal();
  1094.  
  1095.  
  1096. /******************* DoOpenApp **************************/
  1097.  
  1098. pascal OSErr    DoOpenApp ( AppleEvent theAppleEvent,
  1099.                             AppleEvent reply, long refCon )
  1100. {
  1101.     return (noErr);    
  1102. }
  1103.  
  1104.  
  1105. /********************** DoOpenDoc ****************************/
  1106.  
  1107. // This code is essentially derived from code included on the CD with
  1108. //        "Ultimate Mac Programming", by Dave Mark, MacWorld books.
  1109.  
  1110. pascal OSErr    DoOpenDoc( const AppleEvent *theAppleEvent,
  1111.                             AppleEvent *reply, long refCon )
  1112. {
  1113.     FSSpec                file;
  1114.     AEDescList            docList;
  1115.     long                i;
  1116.     long                itemsInList;
  1117.     Size                actualSize;
  1118.     AEKeyword            keyword;
  1119.     DescType            returnedType;
  1120.     OSErr                theErr;
  1121.  
  1122.     // get the direct parameter--a descriptor list--and put it into docList
  1123.     theErr = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
  1124.     if (theErr == noErr)
  1125.     {
  1126.         if (docList.descriptorType != typeAEList)
  1127.         {
  1128.             AEDisposeDesc (&docList);
  1129.             theErr = paramErr;
  1130.         }
  1131.         else
  1132.         {
  1133.             // count the number of descriptor records in the list
  1134.             theErr = AECountItems(&docList, &itemsInList);
  1135.             if (theErr == noErr)
  1136.             {
  1137.                 //get each descriptor record from the list, coerce the returned data
  1138.                 //to an FSSpec and open the associated file
  1139.  
  1140.                 i = 1;
  1141.                 if (itemsInList > i)
  1142.                     DoError(eCantOpenMultiModules);
  1143.  
  1144.                 theErr = AEGetNthPtr(&docList, i, typeFSS, &keyword, &returnedType,
  1145.                                         &file, sizeof(file), &actualSize);
  1146.                 if (theErr == noErr)
  1147.                 {
  1148.                     Open_KidsModule(&file);
  1149.                 }
  1150.             }
  1151.             AEDisposeDesc (&docList);
  1152.         }
  1153.     }
  1154.     return (theErr);
  1155. }
  1156.  
  1157.  
  1158. /************************ DoPrintDoc ***************************/
  1159.  
  1160. pascal OSErr    DoPrintDoc ( AppleEvent theAppleEvent,
  1161.                             AppleEvent reply, long refCon )
  1162. {
  1163.     return (noErr);
  1164. }
  1165.  
  1166.  
  1167. /********************* DoQuitApp *****************************/
  1168.  
  1169. pascal OSErr    DoQuitApp ( AppleEvent theAppleEvent,
  1170.                             AppleEvent reply, long refCon )
  1171. {
  1172.     if (gModuleIsLoaded)
  1173.         Close_KidsModule();
  1174.     gDone = true;
  1175.     return (noErr);
  1176. }
  1177.  
  1178.  
  1179. /******************** DoError *******************************/
  1180.  
  1181. void    DoError( short err )
  1182. {
  1183.     Str255        errString;
  1184.     
  1185.     GetIndString( errString, rErrStringsID, err );
  1186.     
  1187.     ParamText( errString, sEmptyString, sEmptyString, sEmptyString );
  1188.     
  1189.     if ( gFatal )
  1190.     {
  1191.         gDone = true;
  1192.         StopAlert(rErrorAlertID, nil);
  1193.     }
  1194.     else
  1195.         CautionAlert(rErrorAlertID, nil );
  1196.     
  1197. }
  1198.  
  1199.  
  1200. /********************* CheckSystemEnvironment ***************************/ 
  1201.  
  1202. Boolean        CheckSystemEnvironment( void )
  1203. {
  1204.     Boolean            environmentOK = true;
  1205.     long            response;
  1206.     GDHandle        myDevice;
  1207.     PixMapHandle    monitorPMapH;
  1208.     short            depth;
  1209.     
  1210.     /* Kid's Clicks requires System 7 & at least 256 Colors To Operate */
  1211.     
  1212.         /* Check System Version */
  1213.         /* THINK C provides glue code for pre-Sys7 users,
  1214.                                             allowing me to use Gestalt here */
  1215.     Gestalt(gestaltSystemVersion, &response);
  1216.     if (response < kSystemSeven)
  1217.     {
  1218.         environmentOK = false;
  1219.         goto checkDone;
  1220.     }
  1221.     
  1222.         /* Check QuickDraw version */
  1223.      Gestalt(gestaltQuickdrawVersion, &response);
  1224.     if (response >= gestalt8BitQD)
  1225.     {
  1226.         myDevice = GetMainDevice();
  1227.         if (HasDepth(myDevice,8,1,1))    // Does device support 256 Colors?
  1228.         {
  1229.                     /* Check Monitor Current Monitor Depth */
  1230.             monitorPMapH = (**myDevice).gdPMap;
  1231.             depth =  (**monitorPMapH).pixelSize;
  1232.             if (depth < k256ColorDepth)
  1233.                 environmentOK = false;
  1234.         }
  1235.     }
  1236.     else
  1237.         environmentOK = false;    /* Machine does not support 256 Colors */
  1238.  
  1239. checkDone:
  1240.     return (environmentOK); 
  1241. }
  1242.  
  1243.  
  1244. /************************* Pstrcpy *********************************/
  1245.  
  1246. void    Pstrcpy( Str255 *destString, Str255 srcString)
  1247. {
  1248.     PtoCstr(destString);
  1249.     PtoCstr(srcString);
  1250.     strcpy(destString, srcString);
  1251.     CtoPstr(destString);
  1252.     CtoPstr(srcString);
  1253. }